// @Description 认证服务层
// @Author  xiaoyang
// @Date  2025/11/26

package services

import (
	"crypto/md5"
	"errors"
	"fmt"
	"github.com/golang-jwt/jwt/v4"
	"github.com/jinzhu/gorm"
	"golang-manage-admin/http/modules/system/dao"
	"golang-manage-admin/http/modules/system/dto"
	"golang-manage-admin/providers"
	"time"
)

// AuthService 认证服务
type AuthService struct {
	Service
}

// jwtSecret JWT密钥
var jwtSecret = []byte("golang_manager_admin_secret_key_2025")

// jwtClaims JWT声明结构
type jwtClaims struct {
	UserID   uint   `json:"user_id"`
	Username string `json:"username"`
	jwt.RegisteredClaims
}

// Login 用户登录
// 验证用户名密码，生成JWT令牌
func (s *AuthService) Login(form *dto.LoginForm, clientIP string) (*dto.LoginResponse, error) {
	// 获取数据库连接
	tx := providers.Mysqls["resource_share"]
	if tx == nil {
		return nil, errors.New("数据库连接失败")
	}

	// 查询用户
	var user dao.SysUser
	err := tx.Where("username = ?", form.Username).First(&user).Error
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return nil, errors.New("用户名或密码错误")
		}
		return nil, err
	}

	// 验证用户状态
	if user.Status != 1 {
		return nil, errors.New("用户已被禁用")
	}

	// 验证密码
	hashedPassword := s.hashPassword(form.Password)
	if user.Password != hashedPassword {
		return nil, errors.New("用户名或密码错误")
	}

	// 更新最后登录时间和IP
	currentTime := time.Now()
	user.LastLoginAt = &currentTime
	user.LastLoginIp = clientIP
	tx.Save(&user)

	// 生成JWT令牌
	token, expiresAt, err := s.generateJWT(user.ID, user.Username)
	if err != nil {
		return nil, errors.New("生成令牌失败")
	}

	// 获取用户角色和权限
	roles, permissions := s.getUserRolesAndPermissions(user.ID, tx)

	// 构建用户信息
	userInfo := dto.UserInfoResponse{
		ID:          user.ID,
		Username:    user.Username,
		Nickname:    user.Nickname,
		Email:       user.Email,
		Phone:       user.Phone,
		Avatar:      user.Avatar,
		Status:      user.Status,
		Roles:       roles,
		Permissions: permissions,
		LastLoginAt: user.LastLoginAt.Format("2006-01-02 15:04:05"),
	}

	// 构建登录响应
	loginResponse := &dto.LoginResponse{
		Token:     token,
		ExpiresAt: expiresAt,
		UserInfo:  userInfo,
	}

	return loginResponse, nil
}

// Register 用户注册
// 创建新用户账号
func (s *AuthService) Register(form *dto.RegisterForm) (uint, error) {
	// 获取数据库连接
	tx := providers.Mysqls["resource_share"]
	if tx == nil {
		return 0, errors.New("数据库连接失败")
	}

	// 检查用户名是否已存在
	var existingUser dao.SysUser
	err := tx.Where("username = ? OR email = ?", form.Username, form.Email).First(&existingUser).Error
	if err == nil {
		return 0, errors.New("用户名或邮箱已存在")
	}

	// 创建新用户
	newUser := dao.SysUser{
		Username: form.Username,
		Password: s.hashPassword(form.Password),
		Nickname: form.Nickname,
		Email:    form.Email,
		Phone:    form.Phone,
		Status:   1, // 默认启用
	}

	err = tx.Create(&newUser).Error
	if err != nil {
		return 0, errors.New("注册失败")
	}

	// TODO: 可以给新用户分配默认角色

	return newUser.ID, nil
}

// GetUserInfo 获取用户信息
// 根据用户ID获取完整的用户信息
func (s *AuthService) GetUserInfo(userID uint) (*dto.UserInfoResponse, error) {
	// 获取数据库连接
	tx := providers.Mysqls["resource_share"]
	if tx == nil {
		return nil, errors.New("数据库连接失败")
	}

	// 查询用户信息
	var user dao.SysUser
	err := tx.First(&user, userID).Error
	if err != nil {
		return nil, errors.New("用户不存在")
	}

	// 获取用户角色和权限
	roles, permissions := s.getUserRolesAndPermissions(user.ID, tx)

	// 构建用户信息
	userInfo := &dto.UserInfoResponse{
		ID:          user.ID,
		Username:    user.Username,
		Nickname:    user.Nickname,
		Email:       user.Email,
		Phone:       user.Phone,
		Avatar:      user.Avatar,
		Status:      user.Status,
		Roles:       roles,
		Permissions: permissions,
		LastLoginAt: user.LastLoginAt.Format("2006-01-02 15:04:05"),
	}

	return userInfo, nil
}

// ChangePassword 修改密码
// 验证旧密码并更新为新密码
func (s *AuthService) ChangePassword(userID uint, form *dto.ChangePasswordForm) error {
	// 获取数据库连接
	tx := providers.Mysqls["resource_share"]
	if tx == nil {
		return errors.New("数据库连接失败")
	}

	// 查询用户信息
	var user dao.SysUser
	err := tx.First(&user, userID).Error
	if err != nil {
		return errors.New("用户不存在")
	}

	// 验证旧密码
	hashedOldPassword := s.hashPassword(form.OldPassword)
	if user.Password != hashedOldPassword {
		return errors.New("旧密码错误")
	}

	// 更新密码
	user.Password = s.hashPassword(form.NewPassword)
	err = tx.Save(&user).Error
	if err != nil {
		return errors.New("修改密码失败")
	}

	return nil
}

// hashPassword 密码加密
// 使用MD5对密码进行加密处理
func (s *AuthService) hashPassword(password string) string {
	data := []byte(password + "golang_manager_admin_salt")
	return fmt.Sprintf("%x", md5.Sum(data))
}

// generateJWT 生成JWT令牌
// 根据用户ID和用户名生成JWT令牌，返回令牌字符串、过期时间戳和错误信息
func (s *AuthService) generateJWT(userID uint, username string) (string, int64, error) {
	// 设置过期时间为24小时
	expiresAt := time.Now().Add(24 * time.Hour)

	claims := &jwtClaims{
		UserID:   userID,
		Username: username,
		RegisteredClaims: jwt.RegisteredClaims{
			ExpiresAt: jwt.NewNumericDate(expiresAt),
			IssuedAt:  jwt.NewNumericDate(time.Now()),
			NotBefore: jwt.NewNumericDate(time.Now()),
			Issuer:    "golang_manager_admin",
		},
	}

	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
	tokenString, err := token.SignedString(jwtSecret)
	if err != nil {
		return "", 0, err
	}

	return tokenString, expiresAt.Unix(), nil
}

// getUserRolesAndPermissions 获取用户角色和权限
// 根据用户ID从数据库查询用户的角色列表和权限列表
func (s *AuthService) getUserRolesAndPermissions(userID uint, tx *gorm.DB) ([]string, []string) {
	// 这里简化处理，实际应该从数据库查询
	// TODO: 实现从数据库查询用户角色和权限的逻辑

	// 默认返回管理员权限
	roles := []string{"admin"}
	permissions := []string{"*:*:*"}

	return roles, permissions
}

// ValidateToken 验证JWT令牌
// 解析并验证JWT令牌字符串，返回解析后的声明信息和错误信息
func ValidateToken(tokenString string) (*jwtClaims, error) {
	token, err := jwt.ParseWithClaims(tokenString, &jwtClaims{}, func(token *jwt.Token) (interface{}, error) {
		return jwtSecret, nil
	})
	if err != nil {
		return nil, err
	}
	if claims, ok := token.Claims.(*jwtClaims); ok && token.Valid {
		return claims, nil
	}
	return nil, fmt.Errorf("invalid token")
}
